package com.shopping.admin.Intercepter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.shopping.common.core.constant.ErrorCodeEnum;
import com.shopping.common.core.constant.GloatDeletedFlagEnum;
import com.shopping.common.core.constant.JwtEnum;
import com.shopping.common.core.object.ResponseResult;
import com.shopping.common.core.object.TokenData;
import com.shopping.common.core.util.JwtUtil;
import com.shopping.common.core.util.RedisKeyUtil;
import com.shopping.common.sp.model.log.Log;
import com.shopping.service.config.ApplicationConfig;
import com.shopping.service.service.log.LogService;
import jdk.nashorn.internal.parser.Token;
import jodd.util.StringUtil;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.NamedThreadLocal;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

/**
 * @program: shopping-mall
 * @ClassName UserAuthorizationIntercepter
 * @description: 登录权限拦截器
 * @author: zlw
 * @create: 2024-04-16 22:51
 * @Version 1.0
 **/


@Component
public class UserAuthorizationIntercepter extends HandlerInterceptorAdapter {

    @Autowired
    private ApplicationConfig applicationConfig;

    @Autowired
    private RedissonClient redissonClient;

    private Logger logger = LoggerFactory.getLogger(UserAuthorizationIntercepter.class);

    /**
     * 拦截器前置处理
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //业务处理前生效
        String requestURI = request.getRequestURI();
        if(requestURI.contains("/user/login")){
            return true;
        }
        //从请求头拿出token
        String token = request.getHeader("Authorization");
        if(StringUtil.isBlank(token)){
            token = request.getParameter(applicationConfig.getTokenHeadKey());
        }

        //验证token
//        Boolean verify = JwtUtil.verifyToken(token,applicationConfig.getTokenSignKey());
//        if(!verify){
//            response.sendRedirect(request.getContextPath() + "/user/login");
//            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
//            return false;
//        }
        //解析token
        DecodedJWT decodedJWT = JwtUtil.parseToken(token);
        if(JwtUtil.isNullOrExpired(decodedJWT)){
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            this.outputResponseMessage(response, ResponseResult.error(ErrorCodeEnum.UNAUTHORIZED_LOGIN,"用户会话已过期或尚未登录,请重新登录! "));
            return false;
        }
        //* 验证redis是否有该登录信息
        //从解析的token获取redis的sessionId
        String sessionId = (String) decodedJWT.getClaim(JwtEnum.JWT_CLAIM.getKeyName()).asMap().get("sessionId");
        //构建redis的sessionIdKey
        String sessionIdKey = RedisKeyUtil.makeSessionIdKey(sessionId);
        //获取redis的构建redis的sessionIdKey对应的存储对象
        RBucket<String> sessionDataBucket = redissonClient.getBucket(sessionIdKey);
        TokenData tokenData = null;
        if(sessionDataBucket.isExists()){
            //将存储桶的数据转换成JSON格式
            tokenData = JSON.parseObject(sessionDataBucket.get(),TokenData.class);
        }
        if(tokenData == null){
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            this.outputResponseMessage(response,ResponseResult.error(ErrorCodeEnum.UNAUTHORIZED_LOGIN,"用户会话已失效,请重新登录! "));
        return false;
        }
        TokenData.addRequest(tokenData);

        if(JwtUtil.needToRefresh(decodedJWT.getClaim(JwtEnum.JWT_CLAIM.getKeyName()))){
            String refreshToken = JwtUtil.generateToken(decodedJWT.getClaim(JwtEnum.JWT_CLAIM.getKeyName()).asMap(),applicationConfig.getExpiration(),applicationConfig.getTokenSignKey());
            response.addHeader(applicationConfig.getRefreshedTokenHeaderKey(),refreshToken);
        }
        return true;
    }


    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    /**
     * 请求处理后调用,多用于清理资源
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
    private void outputResponseMessage(HttpServletResponse response, ResponseResult<String> respObj)  {
        response.setContentType("application/json; charset=utf-8");
        PrintWriter writer;
        try {
            writer = response.getWriter();
        }catch (IOException e) {
            logger.error("Failed to call OutputResponseMessage.",e);
            return;
        }
        writer.print(JSONObject.toJSONString(respObj));
        writer.flush();
        writer.close();
    }
}
